import type { PageType } from '../../../lib/page_handler/type'
import type {
  EventListenerConfig,
  PlatformEventConfig,
} from '../../../types/constants/event'
import type { ComponentStyleIdType } from '../../../types/interfaces'
import { BaseModule } from '../../../lib/abstract'
import { EventHandler } from '../../../lib/event_handler'
import { PageHandler } from '../../../lib/page_handler'
import {
  BAIDU_RESULT_MARK_SELECTOR,
  BaiduPageType,
} from '../../../lib/page_handler/platform/baidu/types'
import {
  BodyClasses,
  ComponentStyleId,
  InsertPosition,
  logger,
  SUPPORTED_PLATFORMS,
} from '../../../types/constants'
import { ConfigManager } from '../../config_manager'

interface Config {
  enabled?: boolean
}

export class MarkRead extends BaseModule {
  readonly id: string = 'mark_read'
  readonly styleId: string = ComponentStyleId[this.name]
  isInitialized: boolean = false
  readonly supportedPlatforms: string[] = ConfigManager.getInstance().moduleSupportedPlatforms(this.name)
  private static instance: MarkRead
  private pageHandler: PageHandler = PageHandler.getInstance()
  readonly pageType: PageType = this.pageHandler.pages.baidu.pageType
  private readonly eventHandler: EventHandler | undefined
  private readonly EVENT_NAMESPACE = 'markRead'
  private readonly eventConfig: PlatformEventConfig = {}
  private badgeWrapper: string | null = null

  config: Config = {
    enabled: true,
  }

  get name(): ComponentStyleIdType {
    return 'MarkRead'
  }

  constructor() {
    super()

    this.eventConfig = {
      [SUPPORTED_PLATFORMS.BAI_DU]: {
        [BaiduPageType.Web]: [
          {
            selector: `#content_left > ${BAIDU_RESULT_MARK_SELECTOR} h3`,
            container: `#content_left > ${BAIDU_RESULT_MARK_SELECTOR} :is([class*="title-box"], .c-container):has(> h3)`,
            eventType: 'click',
            handler: (e: JQuery.ClickEvent, config: EventListenerConfig) => this.handleMarkRead(e, config),
          },
        ],
        [BaiduPageType.News]: [
          {
            selector: `#content_left > ${BAIDU_RESULT_MARK_SELECTOR} h3`,
            container: `#content_left > ${BAIDU_RESULT_MARK_SELECTOR} h3`,
            eventType: 'click',
            handler: (e: JQuery.ClickEvent, config: EventListenerConfig) => this.handleMarkRead(e, config),
          },
        ],
      },
    }

    this.eventHandler = new EventHandler(this.eventConfig, this.EVENT_NAMESPACE)
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): MarkRead {
    if (!MarkRead.instance) {
      MarkRead.instance = new MarkRead()
    }
    return MarkRead.instance
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.setupEventListeners()
  }

  onToggleCallback(_id: string, checked: boolean, first: boolean): void {
    super.onToggleCallback(_id, checked, first)
  }

  handleCleanupCreatedElements(): void {
    if (!this.badgeWrapper)
      return

    this.pageHandler.features.badge.removeBadge(this.badgeWrapper)
  }

  handleCleanupReferences(): void {
    this.badgeWrapper = null
  }

  handleCleanupOthers(): void {
    this.eventHandler?.destroy()
  }

  setupEventListeners(): void {
    this.eventHandler?.init()
  }

  // TODO: 百度搜索数据来源风格，无法完全覆盖所有情况
  handleMarkRead(e: JQuery.ClickEvent, config: EventListenerConfig): void {
    if (!config.container)
      return

    const $el = $(e.currentTarget)
    this.badgeWrapper = config.container

    if (this.pageType === BaiduPageType.Web) {
      const $resultItem = $el.closest(`${BAIDU_RESULT_MARK_SELECTOR}[tpl]`)
      const resultTpl = $resultItem.attr('tpl') || ''

      // 百度贴吧、百度百科等比较特殊，需要使用 h3 元素
      if ([
        'tieba_general',
        'sg_kg_entity_san',
        'short_video',
        'ly_city_guide_san',
        'ai_ecology',
        'note_lead',
        'note_lead',
      ].includes(resultTpl)) {
        this.badgeWrapper = config.selector
      }
    }

    const $container = $el.closest(this.badgeWrapper)
    $container.addClass(BodyClasses.READ)
    this.addReadBadge($container)
  }

  /**
   * 更新已读徽章
   */
  private addReadBadge($container: JQuery): void {
    const $readBadge = $container.find('.read-badge')

    if ($readBadge.length)
      return

    this.pageHandler.features.badge.addBadge(
      $container,
      'read',
      '已读',
      {
        insertPosition: InsertPosition.Append,
      },
    )
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)

    this.setupEventListeners()

    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }

  getStyles(): string {
    return `
`
  }
}
